package com.binance.assetservice.web.controller;

import com.binance.assetservice.api.IProductApi;
import com.binance.assetservice.data.models.ProductItem;
import com.binance.assetservice.vo.ProductItemVO;
import com.binance.assetservice.vo.request.product.FetchProductsRequest;
import com.binance.assetservice.vo.request.product.GetProductByRuleIdRequest;
import com.binance.assetservice.vo.request.product.GetProductItemRequest;
import com.binance.assetservice.vo.request.product.GetProductSnapshotRequest;
import com.binance.assetservice.vo.request.product.GetSumCirculationBySymbolRequest;
import com.binance.assetservice.vo.request.product.GetUserTradeFeeRequest;
import com.binance.assetservice.vo.request.product.PriceConvertRequest;
import com.binance.assetservice.vo.request.product.RefreshProductRequest;
import com.binance.assetservice.vo.request.product.RefreshUserTradeFeeRequest;
import com.binance.assetservice.vo.request.product.UpdateTradingProductAfterSetFeeRequest;
import com.binance.assetservice.vo.response.product.CurrencyResponse;
import com.binance.assetservice.vo.response.product.FetchProductsResponse;
import com.binance.assetservice.vo.response.product.GetUserTradeFeeResponse;
import com.binance.assetservice.vo.response.product.PriceConvertResponse;
import com.binance.assetservice.vo.response.product.ProductItemResponse;
import com.binance.assetservice.web.cache.IProductSnapshotCache;
import com.binance.assetservice.web.service.IProductService;
import com.binance.master.models.APIRequest;
import com.binance.master.models.APIRequest.VoidBody;
import com.binance.master.models.APIResponse;
import com.binance.master.utils.CopyBeanUtils;
import org.javasimon.aop.Monitored;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@Monitored
public class ProductController implements IProductApi {

    @Autowired
    private IProductService productService;

    @Autowired
    private IProductSnapshotCache productSnapshotCache;

    @Override
    public APIResponse<List<FetchProductsResponse>> fetchProducts(
            @RequestBody @Validated APIRequest<FetchProductsRequest> request) throws Exception {
        return APIResponse.getOKJsonResult(this.productService.fetchProducts(request.getBody()));
    }

    @Override
    public APIResponse<Boolean> getProductSnapshot(
            @RequestBody @Validated APIRequest<GetProductSnapshotRequest> request) throws Exception {
        Boolean sp = productSnapshotCache.getProductSnapshotFlag(request.getBody().getSymbol());
        return APIResponse.getOKJsonResult(sp == null ? false : sp);
    }

    @Override
    public APIResponse<Void> refreshProduct(@RequestBody @Validated APIRequest<RefreshProductRequest> request)
            throws Exception {
        this.productService.refreshProduct(request.getBody().getSymbol(), true);
        return APIResponse.getOKJsonResult();
    }

    @Override
    public APIResponse<Void> refreshProductAll(@RequestBody @Validated APIRequest<VoidBody> request) throws Exception {
        this.productService.refreshProductAll(true);
        return APIResponse.getOKJsonResult();
    }

    @Override
    public APIResponse<GetUserTradeFeeResponse> getUserTradeFee(
            @RequestBody @Validated APIRequest<GetUserTradeFeeRequest> request) throws Exception {
        return APIResponse.getOKJsonResult(this.productService.getUserTradeFee(request.getBody()));
    }

    @Override
    public APIResponse<Void> invalidateAllUserTradeFee(@RequestBody @Validated APIRequest<VoidBody> request)
            throws Exception {
        this.productService.invalidateAllUserTradeFee(true);
        return APIResponse.getOKJsonResult();
    }

    @Override
    public APIResponse<Void> refreshUserTradeFee(@RequestBody @Validated APIRequest<RefreshUserTradeFeeRequest> request)
            throws Exception {
        this.productService.refreshUserTradeFee(request.getBody().getUserId(), request.getBody().getSymbol(), true);
        return APIResponse.getOKJsonResult();
    }

    @Override
    public APIResponse<PriceConvertResponse> priceConvert(
            @RequestBody @Validated APIRequest<PriceConvertRequest> request) throws Exception {
        return APIResponse.getOKJsonResult(this.productService.priceConvert(request.getBody()));
    }

    @Override
    public APIResponse<PriceConvertResponse> mgmtPriceConvert(@RequestBody @Validated  APIRequest<PriceConvertRequest> request)
            throws Exception {
        return APIResponse.getOKJsonResult(this.productService.priceConvert(request.getBody()));
    }

    @Override
    public APIResponse<Double> cnyusd(@RequestBody @Validated APIRequest<VoidBody> request) throws Exception {
        return APIResponse.getOKJsonResult(this.productService.getCnyusd());
    }

    @Override
    public APIResponse<CurrencyResponse> currency(@RequestBody @Validated APIRequest<VoidBody> request)
            throws Exception {
        return APIResponse.getOKJsonResult(this.productService.getCurrency());
    }

    @Override
    public APIResponse<List<String>> getVisibleSymbols(@RequestBody @Validated APIRequest<VoidBody> request)
            throws Exception {
        return APIResponse.getOKJsonResult(this.productService.getVisibleSymbols());
    }

    @Override
    public APIResponse<ProductItemResponse> getAllProducts(@RequestBody @Validated APIRequest<VoidBody> request)
            throws Exception {
        List<ProductItem> list = this.productService.getAllProducts();
        ProductItemResponse response = new ProductItemResponse();
        for (ProductItem pi : list) {
            response.getProductItems().add(CopyBeanUtils.copy(pi, ProductItemVO.class));
        }
        return APIResponse.getOKJsonResult(response);
    }

    @Override
    public APIResponse<ProductItemResponse> getProductItem(
            @RequestBody @Validated APIRequest<GetProductItemRequest> request) throws Exception {
        ProductItemResponse response = new ProductItemResponse();
        ProductItem pi = this.productService.get(request.getBody().getSymbol());
        if (pi != null) {
            response.getProductItems().add(CopyBeanUtils.copy(pi, ProductItemVO.class));
        }
        return APIResponse.getOKJsonResult(response);
    }

    @Override
    public APIResponse<Void> updateTradingProductAfterSetFee(
            @RequestBody @Validated APIRequest<UpdateTradingProductAfterSetFeeRequest> request) throws Exception {
        this.productService.updateProduct(request.getBody().getProductItem());
        return APIResponse.getOKJsonResult();
    }

    @Override
    public APIResponse<ProductItemResponse> getProductByRuleId(
            @RequestBody @Validated APIRequest<GetProductByRuleIdRequest> request) throws Exception {
        List<ProductItem> items = this.productService.getProductByRuleId(request.getBody().getRuleId());
        ProductItemResponse response = new ProductItemResponse();
        for (ProductItem item : items) {
            response.getProductItems().add(CopyBeanUtils.copy(item, ProductItemVO.class));
        }
        return APIResponse.getOKJsonResult(response);
    }

    @Override
    public APIResponse<Double> getSumCirculationBySymbol(
            @RequestBody @Validated APIRequest<GetSumCirculationBySymbolRequest> request) throws Exception {
        return APIResponse
                .getOKJsonResult(this.productService.getSumCirculationBySymbol(request.getBody().getSymbol()));
    }


}
